#include "Acceptor.h"
#include "Logger.h"
#include "InetAddress.h"


#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <unistd.h>


static int createNoblocking()
{
    int sockfd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
    if (sockfd < 0) {
        LOG_FATAL("listen socket create err:%d \n", errno);
    }

    return sockfd;
}

Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenAddr, bool reuseprot)
    : m_loop(loop)
    , m_acceptSocket(createNoblocking()) // socketfd
    , m_acceptChannel(loop, m_acceptSocket.fd())
    , m_listening(false)
{
    m_acceptSocket.setReuseAddr(true);
    m_acceptSocket.setReusePort(true);
    m_acceptSocket.bindAddress(listenAddr); // bind 
    // 当有新用户连接，需要执行一个回调操作
    // baseLoop => acceptChannel => handleRead
    m_acceptChannel.setReadCallback(std::bind(&Acceptor::handleRead, this));
}

Acceptor::~Acceptor()
{
    m_acceptChannel.disableAll();
    m_acceptChannel.remove();
}

void Acceptor::listen()
{
    m_listening = true;
    m_acceptSocket.listen(); // listen
    m_acceptChannel.enableReading(); // m_acceptChannel -> Poller
}

// 当listenfd有事件发生，就有了新用户的连接
void Acceptor::handleRead()
{
    InetAddress peerAddr;
    int connfd = m_acceptSocket.accept(&peerAddr);
    if (connfd >= 0) {
        if (m_newConnectionCallback) {
            // 轮询找到subloop, 并将其唤醒，将任务分发到新的客户端Channel
            m_newConnectionCallback(connfd, peerAddr);
        } else {
            ::close(connfd);
        }
    } else {
        LOG_ERROR("accept err:%d \n", errno);
        // fd不够了
        if (errno == EMFILE) {
            LOG_ERROR("sockfd reached limit ! \n");
        }
    }
}
